//
//  UIImage+Extension2.swift
//  Social
//
//  Created by Hayden on 2019/8/2.
//  Copyright © 2019 shengsheng. All rights reserved.
//

import UIKit

public extension UIImage {
    
    func cropped(to rect: CGRect, withOrientation: Bool) -> UIImage {
        // FIXME: Considering the rect intersection.
        if withOrientation {
            UIGraphicsBeginImageContextWithOptions(rect.size, false, scale)
            draw(at: CGPoint(x: -rect.origin.x, y: -rect.origin.y))
            guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return self }
            UIGraphicsEndImageContext()
            return image
        } else {
            guard rect.size.width < size.width && rect.size.height < size.height else { return self }
            guard let cgImage = cgImage?.cropping(to: rect) else { return self }
            return UIImage(cgImage: cgImage)
        }
    }
    
    func scaled(toMaxEdge length: CGFloat, opaque: Bool = false) -> UIImage? {
        guard max(size.width, size.height) < length else { return self }
        let scale = size.width / size.height
        let newWidth = (scale > 1.0) ? length : (length * scale)
        let newHeight = (scale > 1.0) ? (length / scale) : length
        let newRect = CGRect(0, 0, newWidth, newHeight)
        if #available(iOS 10.0, *) {
            let renderFormat = UIGraphicsImageRendererFormat.default()
            renderFormat.opaque = opaque
            let renderer = UIGraphicsImageRenderer(size: newRect.size, format: renderFormat)
            let newImage = renderer.image { context in draw(in: newRect) }
            return newImage
        } else {
            UIGraphicsBeginImageContextWithOptions(newRect.size, opaque, 0)
            draw(in: newRect)
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return newImage
        }
    }
    
    func scaled(toPercentage percentage: CGFloat, opaque: Bool = false) -> UIImage? {
        let newRect = CGRect(0, 0, size.width * percentage, size.height * percentage)
        UIGraphicsBeginImageContextWithOptions(newRect.size, opaque, 0)
        draw(in: newRect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }
    
    func compressed(toByte byteSize: Int) -> UIImage? {
        return self
    }
    
    func compressedByReducingQuality(toByte byteSize: Int, maxAttempts times: Int = 6) -> UIImage? {
        let outputSizeRange = (min: Int(Double(byteSize) * 0.9), max: byteSize)
        var minQuality: CGFloat = 0.0
        var maxQuality: CGFloat = 1.0
        var outputData: Data?
        for _ in 1...times {
            let currentQuality = (minQuality + maxQuality) / 2
            guard let currentData = jpegData(compressionQuality: currentQuality) else { return nil }
            let currentSize = currentData.count
            if currentSize > outputSizeRange.max {
                maxQuality = currentQuality
            } else if currentSize < outputSizeRange.min {
                minQuality = currentQuality
                outputData = currentData
            } else {
                outputData = currentData
                break
            }
        }
        guard let finalData = outputData else { return nil }
        return UIImage(data: finalData)
    }
    
    func compressedByReducingDimension(toByte byteSize: Int, maxAttempts times: Int = 6) -> UIImage? {
        guard let imageData = jpegData(compressionQuality: 1) else { return nil }
        guard imageData.count > byteSize else { return self }
        var currentImage = self
        for _ in 1...times {
            guard let resizingImage = currentImage.scaled(toPercentage: 0.9) else { return nil }
            guard let currentData = resizingImage.jpegData(compressionQuality: 1) else { return nil }
            currentImage = resizingImage
            if currentData.count < byteSize {
                return currentImage
            }
        }
        return nil
    }
    
    // TODO: deprecated
    func resized(maxLength dimension: CGFloat, opaque: Bool, contentMode: UIView.ContentMode = .scaleAspectFit) -> UIImage {
        
        guard max(size.width, size.height) > dimension else { return self }
        
        var width: CGFloat
        var height: CGFloat
        var newImage: UIImage
        
        let size = self.size
        let aspectRatio =  size.width/size.height
        
        switch contentMode {
        case .scaleAspectFit:
            if aspectRatio > 1 {                          // Landscape image
                width = dimension
                height = dimension / aspectRatio
            } else {                                      // Portrait image
                height = dimension
                width = dimension * aspectRatio
            }
        default:
            fatalError("UIIMage.resizeToFit(): FATAL: Unimplemented ContentMode")
        }
        
        if #available(iOS 10.0, *) {
            let renderFormat = UIGraphicsImageRendererFormat.default()
            renderFormat.opaque = opaque
            let renderer = UIGraphicsImageRenderer(size: CGSize(width: width, height: height), format: renderFormat)
            newImage = renderer.image {
                (context) in
                self.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), opaque, 0)
            self.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
            newImage = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
        }
        
        return newImage
    }
    
    
    
}
